package middleware

import (
	"admin/contrib/session"
	"admin/model"
	"common/helper"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/valyala/fasthttp"
	"regexp"
	"strings"
)

var allows = map[string]bool{
	"/tenant/login":               true,
	"/tenant/admin/login":         true,
	"/merchant/login":             true,
	"/business/login":             true,
	"/api/betcat/callback":        true,
	"/api/u2cpay/callback":        true,
	"/api/pay4/callback":          true,
	"/api/report/fixdailydata":    true,
	"/api/report/fixgamedaily":    true,
	"/api/withdraw/toThird123qwe": true,
	"/api/gettotaldata":           true,
	"/api/to/merchant2":           true,
}

type validTokenRes struct {
	Code int         `cbor:"code" json:"code"`
	Msg  string      `cbor:"msg" json:"msg"`
	Data interface{} `cbor:"data" json:"data"`
}

func CheckTokenMiddleware(ctx *fasthttp.RequestCtx) error {

	path := string(ctx.Path())
	body := string(ctx.PostBody())
	mapValue, err := session.AdminCheck(ctx)
	ip := helper.FromRequest(ctx)

	if path == "/tenant/admin/login" || path == "/merchant/login" || path == "/business/login" {

		if model.WhiteListCheck(ip) {
			return errors.New("访问受限")
		}
		// 1分钟内，200次调用 封ip
		model.WhiteListLimit(ip)
	}

	//保存全部接口访问记录
	helper.InfoLog("后台接口访问：地址：%s---操作人ID：%s---%s---参数：%s", path, mapValue["id"], ip, body)

	if containsSQLKeywords(body) {
		res, _ := json.Marshal(validTokenRes{
			Code: 1,
			Msg:  "error",
		})
		return errors.New(string(res))
	}
	//body = stripTags(body)
	ctx.SetBody([]byte(htmlspecialchars(body)))

	if _, ok := allows[path]; ok {
		return nil
	}
	res, _ := json.Marshal(validTokenRes{
		Code: 1,
		Msg:  "token error",
	})
	model.InsertAdminLog("1", mapValue["id"], "", path, body, ip)

	if err != nil {
		return errors.New(string(res))
	}
	//密码验证
	oldPasseord := mapValue["password"]
	if mapValue["loginuser"] == "admin" {
		admin, _ := model.GetAdminInfoById(mapValue["id"])
		if admin.Pwd != oldPasseord {
			//删除t

			model.AdminLogout(ctx)
			return errors.New(string(res))
		}
	}
	if mapValue["loginuser"] == "merchant" {
		merchant, _ := model.GetOperatorInfoById(mapValue["id"])
		if merchant.Password != oldPasseord {
			return errors.New(string(res))
		}
	}
	if mapValue["loginuser"] == "business" {
		business, _ := model.GetBusinessInfoById(mapValue["id"])
		if business.Password != oldPasseord {
			return errors.New(string(res))
		}
	}
	return nil
}

func htmlspecialchars(input string) string {
	replacer := strings.NewReplacer(
		"&", "&amp;",
		"\"", "&quot;",
		"'", "&#039;",
		"<", "&lt;",
		">", "&gt;",
	)
	return replacer.Replace(input)
}

func stripTags(input string) string {
	// Compile the regex to match HTML tags
	re := regexp.MustCompile(`<.*?>`)
	// Replace all HTML tags with an empty string
	output := re.ReplaceAllString(input, "")
	return output
}

func containsSQLKeywords(input string) bool {
	sqlKeywords := []string{
		`SELECT`, `INSERT`, `UPDATE`, `DELETE`, `DROP`, `CREATE`, `ALTER`, `TRUNCATE`,
		`MERGE`, `CALL`, `EXEC`, `EXECUTE`, `UNION`, `EXPLAIN`, `GRANT`, `REVOKE`, `SAVEPOINT`,
		`ROLLBACK`, `TRANSACTION`,
	}
	for _, keyword := range sqlKeywords {
		// Use case-insensitive matching
		match, err := regexp.MatchString(`(?i)\b`+keyword+`\b`, input)
		if err != nil {
			fmt.Println("Error compiling regex: ", err)
			return false
		}
		if match {
			return true
		}
	}
	return false
}
